package com.zzyl.intercept;

import cn.hutool.core.map.MapUtil;
import com.zzyl.constant.Constants;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.properties.JwtTokenManagerProperties;
import com.zzyl.utils.JwtUtil;
import com.zzyl.utils.ObjectUtil;
import com.zzyl.utils.UserThreadLocal;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
 * @Description UserInterceptor
 * @Author liangDong
 * @Date 2025-05-16  16:08
 */
@Component
@Slf4j
public class UserInterceptor implements HandlerInterceptor {
    @Autowired
    private JwtTokenManagerProperties jwtTokenManagerProperties;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
         String token = request.getHeader(Constants.USER_TOKEN);
         log.info("开始解析 customer user token:{}",token);
         if (ObjectUtil.isEmpty(token)) {
             throw new BaseException(BasicEnum.SECURITY_ACCESSDENIED_FAIL);
         }

    //     校验jwt
        Map<String,Object> claims = null;
        try {
            claims = JwtUtil.parseJWT(jwtTokenManagerProperties.getBase64EncodedSecretKey(),token);
            if (ObjectUtil.isEmpty(claims)){
                //token失效
                throw new BaseException(BasicEnum.SECURITY_ACCESSDENIED_FAIL);
            }
        }catch (Exception e){
        //    token失效
            throw new BaseException(BasicEnum.SECURITY_ACCESSDENIED_FAIL);
        }

    //    获取用户id
        Long userId = MapUtil.get(claims,Constants.JWT_USERID, Long.class);
        if (ObjectUtil.isEmpty(userId)) throw new BaseException(BasicEnum.SECURITY_ACCESSDENIED_FAIL);

    //    存入当前请求线程
        UserThreadLocal.set(userId);
    //    上述的操作都没问题才能返回true
        return true;
    }

    //如果使用springmvc的拦截器，建议remove动作要在afterCompletion方法中执行，因为如果目标方法报错了，是不会执行postHandle方法的，而afterCompletion不管目标方法是否报错都会执行
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    //    响应结束后，清理ThreadLocal内的数据，防止内存泄露，此处必须使用afterCompletion,这样就算有异常也会执行
        UserThreadLocal.remove();
    }
}
